home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bfsorts.arc / MLSORT.C < prev    next >
C/C++ Source or Header  |  1991-07-09  |  5KB  |  198 lines

  1. /***********************************************************************/
  2. /*  SORT(): Non-Recursive Merge List Sort function.                    */
  3. /*  See the function declaration for calling information.              */
  4. /* Function is by Bruce Feist; please contact me on CompuServe with    */
  5. /*    a message on BPROGB, MACDEV, or EASYPLEX if you have any         */
  6. /*    questions or problems.                                           */
  7. /* You can also reach me at the Enlightened Board, at (703) 370-9528,  */
  8. /*   N/8/1                                                             */
  9. /* Feel free to make use of this code in your own programs.            */
  10. /***********************************************************************/
  11. /* Merge/List sort.  Fast, but uses even more space than msort. */
  12. /* Like merge sort, but takes advantage of any preexisting ordered sublists. */
  13.  
  14. #include <alloc.h>
  15. #include <mem.h>
  16. #include <stddef.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19.  
  20. #include "sort.h"
  21.  
  22. #define ENDLIST -1
  23. #define VERBOSE (0)
  24.  
  25. static char *base;
  26. static unsigned int nelem, width;
  27. static int (*compare) (void *, void *);
  28. static int merge (int left, int right);
  29. static void show_lists (int *lists, int nlists);
  30. static void show_list (int list);
  31.  
  32. static int  *next;  /* array: which element comes after this one? */
  33.  
  34. int
  35. mlsort (void *pbase, size_t pnelem, size_t pwidth, int pcompare())
  36. {
  37.   int *lists; /* array of pointers to sorted sublists */
  38.   unsigned int nlists, list_num;
  39.   int elem_num, temp_num;
  40.   char *temp_base;
  41.   int workspace_size;
  42.   void *workspace;  /* contains lists or temp_base, depending on when */
  43.  
  44.   base = pbase;
  45.   nelem = pnelem;
  46.   width = pwidth;
  47.   compare = pcompare;
  48.  
  49. #if VERBOSE
  50.   printf ("MLsort (%p, %d, %d, %p).\n", pbase, pnelem, pwidth, pcompare);
  51. #endif
  52.  
  53.   workspace_size = nelem * max (sizeof (*lists) + sizeof (*next), width);
  54.   workspace = malloc (workspace_size);
  55.   if (workspace == NULL)
  56.     return S_NOMEM;
  57.  
  58.   temp_base = workspace;
  59.   lists = workspace;     /* it's never used concurrently with temp_base! */
  60.  
  61.   next = malloc (nelem * sizeof (*next));
  62.   if (next == NULL)
  63.     return S_NOMEM;
  64.  
  65.   lists[0] = 0;
  66.   nlists = 1;
  67.  
  68.   for (elem_num = 1;
  69.        elem_num < nelem;
  70.        elem_num++)
  71.   {
  72.     if (compare(base + (elem_num - 1) * width,
  73.         base + elem_num * width) > 0)
  74.     {
  75.       next [elem_num - 1] = ENDLIST;
  76.       lists [nlists] = elem_num;
  77.       nlists++;
  78.       }
  79.     else
  80.     {
  81.       next [elem_num - 1] = elem_num;
  82.       }
  83.     } /* end for */
  84.   next [nelem - 1] = ENDLIST;
  85.  
  86.   while (nlists > 1)
  87.   {  /* Merge pairs of lists */
  88.     for (list_num = 0;
  89.      list_num < (nlists - 1);
  90.      list_num++, nlists--)
  91.     {
  92. #if VERBOSE
  93.       show_lists (lists, nlists);
  94.       printf ("\nMerging list %d with list %d:\n", list_num, list_num + 1);
  95. #endif
  96.       lists[list_num] = merge (lists[list_num], lists[list_num + 1]);
  97.       lists[list_num + 1] = lists[nlists - 1];
  98.       } /* end for */
  99.     } /* end while */
  100.  
  101. #if VERBOSE
  102.   show_lists (lists, nlists);
  103. #endif
  104.  
  105.   /* move everything to where it belongs. */
  106.  
  107.   for (elem_num = 0, temp_num = lists[0];
  108.        elem_num < nelem;
  109.        elem_num++, temp_num = next [temp_num])
  110.   {
  111.     memcpy (temp_base + width * elem_num, base + width * temp_num, width);
  112.     }
  113.  
  114.   memcpy (base, temp_base, width * nelem);
  115.  
  116.   return S_OK;
  117.   }  /* end msort */
  118.  
  119.  
  120. int
  121. merge (int left, int right)
  122. {
  123.   int first, last;
  124.   char *left_ptr, *right_ptr;
  125.  
  126.   left_ptr = base + left * width;
  127.   right_ptr = base + right * width;
  128.  
  129.   if (compare (left_ptr, right_ptr) > 0)
  130.   {
  131.     first = last = right;
  132.     right = next [right];
  133.     right_ptr = base + right * width;
  134.     }
  135.   else
  136.   {
  137.     first = last = left;
  138.     left = next [left];
  139.     left_ptr = base + left * width;
  140.     }
  141.  
  142.   while (left != ENDLIST && right != ENDLIST)
  143.   {
  144.     if (compare (left_ptr, right_ptr) > 0)
  145.     {
  146.       /* right is smaller; use it */
  147.       next [last] = right;
  148.       last = right;
  149.       right = next [right];
  150.       right_ptr = base + right * width;
  151.       }
  152.     else
  153.     {
  154.       /* left is smaller; use it */
  155.       next [last] = left;
  156.       last = left;
  157.       left = next [left];
  158.       left_ptr = base + left * width;
  159.       }
  160.     }
  161.  
  162.   next [last] = (left == ENDLIST) ? right : left;
  163.  
  164.   return first;
  165.   } /* end merge */
  166.  
  167.  
  168. void
  169. show_lists (int *lists, int nlists)
  170. {
  171.   int list;
  172.  
  173.   for (list = 0;
  174.        list < nlists;
  175.        list++)
  176.   {
  177.     printf ("List # %d at ", list);
  178.     show_list (lists [list]);
  179.     } /* end for */
  180.   } /* end show_lists */
  181.  
  182.  
  183. #pragma warn -use
  184. void
  185. show_list (int list)
  186. {
  187.   int node;
  188.  
  189.   printf ("%d: ", list);
  190.   for (node = list;
  191.        node != ENDLIST;
  192.        node = next [node])
  193.   {
  194.     printf ("# %d: %.4lf, ", node, *((double *) (base + node * width)));
  195.     }
  196.   printf ("\n");
  197.   } /* end show */
  198.